﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain;
using Casamiel.Domain.Entity;

using Casamiel.Domain.Request;
using Casamiel.Domain.Response;
using Casamiel.Domain.Response.IC;
using MediatR;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Casamiel.Application.Commands.Pre
{
	public sealed class CreateOrderCommandHandler : BaseCommandHandler, IRequestHandler<CreateOrderCommand, BaseResult<PaymentRsp>>
	{
		private readonly NLog.ILogger _logger = NLog.LogManager.GetLogger("WaimaiService");
		private readonly IMbrStoreRepository _mbrStoreRepository;
		private readonly IMemberCardRepository _memberCardRepository;
		private readonly ICasaMielSession _session;
		private readonly IMemberRepository _memberRepository;
		private readonly IPaymentRecordRepository _paymentRecordRepository;
		private readonly INoticeBaseRepository _noticeBase;
		private readonly IUserLogRepository _userLogRepository;
		private readonly IOrderBaseRepository _orderBaseRepository;
		private readonly IMemberCouponRepository _memberCouponRepository;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="netICService"></param>
		/// <param name="httpClientFactory"></param>
		/// <param name="settings"></param>
		/// <param name="mbrStoreRepository"></param>
		/// <param name="userLogRepository"></param>
		/// <param name="noticeBaseRepository"></param>
		/// <param name="memberCardRepository"></param>
		/// <param name="session"></param>
		/// <param name="paymentRecordRepository"></param>
		/// <param name="orderBaseRepository"></param>
		/// <param name="memberRepository"></param>
		/// <param name="memberCouponRepository"></param>
		public CreateOrderCommandHandler(INetICService netICService, IHttpClientFactory httpClientFactory, IOptionsSnapshot<CasamielSettings> settings,
		IMbrStoreRepository mbrStoreRepository, IUserLogRepository userLogRepository, INoticeBaseRepository noticeBaseRepository, IMemberCardRepository memberCardRepository,
		ICasaMielSession session, IPaymentRecordRepository paymentRecordRepository, IOrderBaseRepository orderBaseRepository, IMemberRepository memberRepository, IMemberCouponRepository memberCouponRepository) : base(netICService, httpClientFactory, settings)
		{
			_mbrStoreRepository = mbrStoreRepository;
			_memberCardRepository = memberCardRepository;
			_session = session;
			_paymentRecordRepository = paymentRecordRepository;
			_noticeBase = noticeBaseRepository;
			_userLogRepository = userLogRepository;
			_orderBaseRepository = orderBaseRepository;
			_memberRepository = memberRepository;
			_memberCouponRepository = memberCouponRepository;
		}
		/// <summary>
		/// Handle the specified request and cancellationToken.
		/// </summary>
		/// <returns>The handle.</returns>
		/// <param name="request">Request.</param>
		/// <param name="cancellationToken">Cancellation token.</param>
		public async Task<BaseResult<PaymentRsp>> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
		{

			if (request == null) {
				throw new ArgumentNullException(nameof(request));
			}

			this._logger.Trace($"PreCreateOrder,{JsonConvert.SerializeObject(request)}");

			if (request.Paymethod == 0) {
				request.Paymethod = 4;
			}
			var Discount = 0m;
			var storeinfo = await _mbrStoreRepository.GetByStoreIdAsync<ICasaMielSession>(request.StoreId).ConfigureAwait(false);
			if (storeinfo == null) {
				return new BaseResult<PaymentRsp>(null, 9999, "门店信息有误！");
			}

			//if (storeinfo.IsWaimaiShopClose == 1) {
			//	return new BaseResult<PaymentRsp>(null, 9999, "抱歉门店不支持外卖服务！");
			//}
			//if (storeinfo.IsWaimaiClose == 1) {
			//	return new BaseResult<PaymentRsp>(null, 9999, "还未开店！");
			//}
			 
			 
			var OrderAmount = 0m;
			var stockreq = new ProductStockQueryReq { shopid = storeinfo.RelationId, product = new List<ProductStockReq>() };

			foreach (var item in request.GoodsList) {
				stockreq.product.Add(new ProductStockReq {
					pid = $"{item.GoodsRelationId}",
					count = item.GoodsQuantity
				});

				//  OrderAmount += item.Price * item.GoodsQuantity;
			}
			OrderAmount = request.GoodsList.Sum(a => a.Price * a.GoodsQuantity);
			 



			var cardlist = await _memberCardRepository.GetListAsync<ICasaMielSession>(request.Mobile).ConfigureAwait(false);
			var _cardno = "";
			var _cardtype = 1;
			var vipcard = cardlist.SingleOrDefault(c => c.IsBind == true && (c.CardType == $"{(int)CardType.Ic}" || c.CardType == $"{(int)CardType.ECard}"));

			if (vipcard != null) {
				_cardno = vipcard.CardNO;
			}
			//string discountCouponName = "";
			double rebate = 0;
			//if (this.Casasettings.ApiName == "casamielnetwork") {
			//if (DateTime.Now.Month >= 7) {
			//	if (OrderAmount >= 40) {
			//		rebate = 5;
			//	}
			//}
			//}
			var entity = await _memberRepository.FindAsync<ICasaMielSession>(request.Mobile).ConfigureAwait(false);
			if (entity == null) {
				return new BaseResult<PaymentRsp>(null, 9999, "会员不存在");
			}

			if (request.DiscountList != null && request.DiscountList.Any()) {

				decimal ticketInfoPrice;
				ICResult ticketLimit;
				if (request.DiscountList.Count > 1) {
					return new BaseResult<PaymentRsp>(null, 9999, "券只能用一张");
				}
				if (request.DiscountList[0].DiscountCouponType == 1) {

					if (request.DiscountList[0].CardNo == "") {
						request.DiscountList[0].CardNo = _cardno;
					}
					var ticketreq = new GetTicticketReq { Cardno = request.DiscountList[0].CardNo, Pagesize = 200, State = 2, Pageindex = 1 };
					Iclogger.Trace($"GeticticketReq:{JsonConvert.SerializeObject(ticketreq)}");
					var a = await NetICService.Geticticket(ticketreq).ConfigureAwait(false);
					if (a.code == 0) {
						var list = JsonConvert.DeserializeObject<TicketItemRoot>(a.content);
						var ticket = list.Tickets.SingleOrDefault(t => t.Ticketid == request.DiscountList[0].DiscountCouponId);
						if (ticket != null) {
							request.DiscountList[0].DiscountCouponMoney = ticket.Je.ToDecimal(0);
							ticketInfoPrice = request.DiscountList[0].DiscountCouponMoney;
							Discount = ticketInfoPrice;

						} else {
							return new BaseResult<PaymentRsp>(null, -23, "优惠券不可用");
						}

					} else {
						return new BaseResult<PaymentRsp>(null, -23, "优惠券不可用");
					}
					var tt = new List<long>() { request.DiscountList[0].DiscountCouponId };
					ticketLimit = await NetICService.TicketLimit(storeinfo.RelationId, tt, 1, true).ConfigureAwait(false);
				} else if (request.DiscountList[0].DiscountCouponType == 2) {
					var memberCoupon = await _memberCouponRepository.GetKeyAsync<ICasaMielSession>(request.DiscountList[0].DiscountCouponId).ConfigureAwait(false);
					if (memberCoupon == null || memberCoupon.MID != entity.ID) {
						return new BaseResult<PaymentRsp>(null, 9999, "券不存在");
					}

					Discount = memberCoupon.Price;
					var ticketInfoRsp = await NetICService.Tmticketquery(new Domain.Request.IC.TmticketqueryReq { ticketcode = memberCoupon.Ticketcode }).ConfigureAwait(false);
					if (ticketInfoRsp.code != 0) {

						return new BaseResult<PaymentRsp>(null, ticketInfoRsp.code, ticketInfoRsp.msg);

					}
					var ticketInfo = JObject.Parse(ticketInfoRsp.content);

					ticketInfoPrice = ticketInfo["price"].ToString().ToDecimal(0);


					//a.Productname = ticketInfo["productname"].ToString();
					//a.Productid = ticketInfo["productid"].ToInt64(0);
					var State = ticketInfo["state"].ToInt16(0);
					//a.Startdate = DateTime.Parse(ticketInfo["startdate"].ToString(), CultureInfo.InvariantCulture);
					//a.Enddate = DateTime.Parse(ticketInfo["enddate"].ToString(), CultureInfo.InvariantCulture);
					if (State != 3) {
						return new BaseResult<PaymentRsp>(null, 9999, "券不可用");
					}
					var ids = new List<long> {
								memberCoupon.Productid
							};
					ticketLimit = await NetICService.TicketLimit(storeinfo.RelationId, memberCoupon.Ticketcode).ConfigureAwait(false);
				} else {
					return new BaseResult<PaymentRsp>(null, 9999, "券类型有误");
				}
				var rule = JsonConvert.DeserializeObject<TicketsRules>(ticketLimit.content);
				//51、当前券要求最低的单据金额，limitvalue为单据金额
				//21、券仅允许消费的产品，limitvalue 为限制的产品标识
				//215、券必须消费的产品，limitvalue 为限制的产品标识
				//216、券需要消费的产品(之一)，limitvalue 为限制的产品标识，和 215 不同，216 只需要有一种产品就可以了，如果 limitvalue 只有一种产品，则和 215 效果相同
				//22、券不允许消费的产品，limitvalue 为限制的产品标识

				var list216 = rule.Tickets.Where(c => c.Limittype == 216);
				if (list216.Any()) {
					bool s = false;
					var list216msg = "";
					foreach (var item in list216) {
						var ss = request.GoodsList.Count(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture));
						if (ss > 0) {
							s = true;
						} else {
							list216msg += $"{item.Productname}{item.Limitdesc}";
						}
					}
					if (!s) {
						//list.Tickets[i].State = 0;
						return new BaseResult<PaymentRsp>(null, 9999, list216msg);
					}
					Discount = ticketInfoPrice;
				}

				var list215 = rule.Tickets.Where(c => c.Limittype == 215);
				if (list215.Any()) {
					var list215sucess = true;
					var amsg = "";
					foreach (var item in list215) {
						if (!request.GoodsList.Any(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture))) {
							amsg += $"{item.Productname}{item.Limitdesc}";
							list215sucess = false;
						}
					}
					if (!list215sucess) {
						//list.Tickets[i].State = 0;
						return new BaseResult<PaymentRsp>(null, 9999, amsg);
					}
					Discount = ticketInfoPrice;
				}
				var abc = rule.Tickets;
				foreach (var item in abc) {
					if (item.Limittype == 51) {
						var tamount = OrderAmount;

						if (tamount < item.Limitvalue.ToDecimal(0)) {
							//list.Tickets[i].State = 0;
							return new BaseResult<PaymentRsp>(null, 9999, item.Limitdesc);
						}
						Discount = ticketInfoPrice;
					}
					if (item.Limittype == 21) {
						var aa = request.GoodsList.Where(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture)).ToList();
						if (aa.Any()) {
							//list.Tickets[i].State = 0;
							return new BaseResult<PaymentRsp>(null, 9999, item.Limitdesc);
						}
						Discount = aa[0].Price;
					}
					if (item.Limittype == 22) {
						var aa = request.GoodsList.Count(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture));
						if (aa > 0) {
							//list.Tickets[i].State = 0;
							return new BaseResult<PaymentRsp>(null, 9999, item.Limitdesc);
						}
						Discount = ticketInfoPrice;
					}
				}
			}


			if (request.Paymethod == 3) {

				var card = cardlist.SingleOrDefault(c => c.CardNO == request.PayCardNO && c.IsBind == true);
				if (card != null) {
					if (card.CardType == "3") {
						_cardtype = 3;
					}
				} else {
					return new BaseResult<PaymentRsp>(null, 999, "卡号有误");
				}
				var paymoney = OrderAmount - rebate.ToString(CultureInfo.InvariantCulture).ToDecimal(0) - Discount;
				paymoney = OrderAmount - Discount;
				//if (paymoney < 0) {
				//	paymoney = request.FreightMoney;
				//} else {
				//	paymoney += request.FreightMoney;
				//}

				var zcard = await NetICService.Iclessquery(request.PayCardNO, $"{request.Source}099".ToInt32(0)).ConfigureAwait(false);
				if (zcard.code == 0) {
					var cardinfo = JsonConvert.DeserializeObject<JObject>(zcard.content);
					var balance = cardinfo["totalmoney"].ToDecimal(0);
					if (balance < paymoney) {
						if (_cardtype == 3)//幸福卡
						{
							return new BaseResult<PaymentRsp>(null, -40, "卡内余额不足");
						}
						return new BaseResult<PaymentRsp>(null, -39, "卡内余额不足");
					}
				} else {
					return new BaseResult<PaymentRsp>(null, zcard.code, zcard.msg);
				}
			}
			  
			var icdto = new IcconsumeReq {
				Rebate = rebate,
				Phoneno = request.Mobile,
				Cardno = _cardno,
				Shopid = storeinfo.RelationId,
				Pickuptime = DateTime.Now.AddMinutes(10).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture)
			};
			icdto.Product = new List<IcconsumeReq.IcconsumeProductItem>();
			foreach (var item in request.GoodsList) {
				icdto.Product.Add(new IcconsumeReq.IcconsumeProductItem { Pid = $"{item.GoodsRelationId}", Count = item.GoodsQuantity });

			}
			var icentity = await NetICService.Icconsume(icdto).ConfigureAwait(false);
			if (icentity.code == 0) {
				var jobject = JsonConvert.DeserializeObject<JObject>(icentity.content);
				request.IcTradeNO = jobject["tradeno"].ToString();
				request.BillNo = jobject["billno"].ToString();
			} else {
				return new BaseResult<PaymentRsp>(null, icentity.code, icentity.msg);
			}
			var backreq = new IcConsumeBackReq { Tradeno = request.IcTradeNO };
			
			//var data = new {
			//	request.ConsigneeId, request.ContactName, request.ContactPhone,
			//	request.CostPrice, request.GoodsList,
			//	request.InvoiceId, request.StoreId, rebate, request.TakeTime, request.Paymethod, request.Remark,
			//	request.OrderType, request.Mobile, request.DiscountList, request.IcTradeNO, request.FreightMoney
			//};
			OrderCreateRsp order;
			try {
				OrderLogger.Trace(JsonConvert.SerializeObject(request));
				var url = "Pred/v3/Order/Create";

				var result = await PostAsync<ThirdResult<OrderCreateRsp>>(url, JsonConvert.SerializeObject(request)).ConfigureAwait(false);
				_logger.Trace($"PredcreateOrder:{JsonConvert.SerializeObject(result)}");
				// var dynamicdata = JsonConvert.DeserializeObject<JObject>(result);
				if (result.IsSuccess) {
					order = result.Data;// JsonConvert.DeserializeObject<Order_CreateRsp>(dynamicdata["data"].ToString());
				} else {
					var d = await NetICService.Icconsumeback(backreq).ConfigureAwait(false);
					_logger.Error($"PredcreateOrder:{JsonConvert.SerializeObject(d)}");
					return new BaseResult<PaymentRsp>(null, 9999, result.ResultRemark);
				}
			} catch (System.Net.Sockets.SocketException) {
				var d = await NetICService.Icconsumeback(backreq).ConfigureAwait(false);
				_logger.Error($"Pred:{JsonConvert.SerializeObject(backreq)},rsp:{JsonConvert.SerializeObject(d)}");
				throw;
			}

			if (order.PayMoney == 0) {
				request.Paymethod = 3;
			}
			var entity1 = await _orderBaseRepository.GetByOrderCodeAsync<ICasaMielSession>(order.OrderCode).ConfigureAwait(false);

			var p_tradeno = $"C{DateTime.Now.ToString("yyMMddHHmmssfff", CultureInfo.CurrentCulture)}";
			var payment = new PaymentRecord {
				OperationMethod = (int)OperationMethod.Pre,
				TradeNo = p_tradeno,
				Amount = (OrderAmount - Discount).ToString(CultureInfo.CurrentCulture).ToDouble(0) - rebate,
				PayMethod = request.Paymethod,
				BillNO = order.OrderCode,
				IcTradeNO = request.IcTradeNO,
				State = 0,
				OperationState = 0,
				CreateTime = DateTime.Now,
				Mobile = request.Mobile
			};
			switch (request.Paymethod) {
				case 3://会员卡
					var pay = new IcConsumepayReq {
						Phoneno = request.Mobile,
						Cardno = request.PayCardNO,
						Shopid = storeinfo.RelationId,
						Tradeno = request.IcTradeNO,
						Createinvoice = true
					};

					var paymoney = order.PayMoney;
					if (this.Casasettings.ApiName == "doncoApi") {
						paymoney = order.OrderMoney - entity1.DiscountMoney - entity1.FreightMoney;
						if (paymoney < 0) {
							paymoney = entity1.FreightMoney;
						} else {
							paymoney += entity1.FreightMoney;
						}
					}
					pay.Paycontent = new List<IcConsumepayReq.PaycontentItem>
					{

						new IcConsumepayReq.PaycontentItem
						{
							Paytype = "3",
							Paymoney = paymoney.ToDouble(0),
							Paytradeno = $"c{DateTime.Now.ToString("yyMMddHHmmssffff",CultureInfo.CurrentCulture)}"
						}

					};

					if (this.Casasettings.ApiName == "doncoApi") {

					}
					foreach (var x in request.DiscountList) {
						var _paytype = "5";
						var _payuser = $"{ x.DiscountCouponId }";
						if (x.DiscountCouponType == 1) {
							_paytype = "6";
						} else {
							var Coupon = await _memberCouponRepository.GetKeyAsync<ICasaMielSession>(x.DiscountCouponId).ConfigureAwait(false);
							_payuser = Coupon.Ticketcode;
						}

						pay.Paycontent.Add(new IcConsumepayReq.PaycontentItem {
							Paytype = _paytype,
							Paymoney = $"{ x.DiscountCouponMoney}".ToDouble(0),
							Paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CreateSpecificCulture("en-US"))}",
							Payuser = _payuser
						});
					}
					//if (request.DiscountCouponId > 0) {
					//	pay.Paycontent.Add(new IcConsumepayReq.PaycontentItem {
					//		Paytype = "6",
					//		Paymoney = $"{request.DiscountCouponMoney}".ToDouble(0),
					//		Paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CurrentCulture)}",
					//		Payuser = $"{request.DiscountCouponId}"
					//	});
					//}
					//if (request.FreightMoney > 0) {
					//	pay.Payfee = new List<IcConsumepayReq.PayfeeItem>{new IcConsumepayReq.PayfeeItem
					//	{
					//		Fee = request.FreightMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
					//		Feetype="1",
					//		Description = "配送费"
					//	}};
					//}

					var zmodel = await NetICService.Icconsumepay(pay).ConfigureAwait(false);
					if (zmodel.code == 0) {
						var jobject = JsonConvert.DeserializeObject<JObject>(zmodel.content);
						if (jobject != null && jobject["invoiceqrcode"] != null) {
							var invoiceUrl = jobject["invoiceqrcode"].ToString();
							await _orderBaseRepository.UpdateOrderInvoiceUrlByOrderCodeAsync<ICasaMielSession>(payment.BillNO, invoiceUrl).ConfigureAwait(false);
						} else {
							BizInfologger.Error($"Invoideurl:{zmodel.content}");
						}

						using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
							payment.State = 1;
							payment.Remark = $"会员卡：{request.PayCardNO}";
							payment.OperationState = 1;
							payment.PayTime = DateTime.Now;
							await _paymentRecordRepository.SaveAsync(payment, uow).ConfigureAwait(true);
							//var noticEntity = new NoticeBaseEntity() {
							//	RemindTime = DateTime.Now.AddMinutes(-3),
							//	CreateTime = DateTime.Now,
							//	RelationId = order.OrderBaseId,
							//	StoreId = request.StoreId,
							//	NoticeType = 0
							//};
							//await _noticeBase.SaveAsync(noticEntity, uow).ConfigureAwait(true);
						}
						var logdata = new UserLog { Url = request.RequestUrl, OPInfo = $"外卖单支付,卡号:[{request.PayCardNO},支付金额{order.PayMoney}，订单号：{order.OrderCode}", OPTime = DateTime.Now, UserName = request.Mobile };
						await _userLogRepository.SaveAsync<ICasaMielSession>(logdata).ConfigureAwait(false);
						await PreOrderChangeStatus(order.OrderCode, request.Mobile, 1, request.Paymethod, "").ConfigureAwait(false);
						var p = new PaymentRsp { Payed = true, PayMethod = 3, Paymentrequest = "", OrderCode = order.OrderCode };
						return new BaseResult<PaymentRsp>(p, 0, "");
					} else {
						return new BaseResult<PaymentRsp>(null, zmodel.code, zmodel.msg);
					}
				default:
					//var command = new CreatePaymentRequestCommand(payment, data.id);
					//var result = await _mediator.Send(command).ConfigureAwait(false);
					//return Ok(new { code = 0, content = result });
					var pp = new PaymentRsp { Payed = false, PayMethod = request.Paymethod, Paymentrequest = $"{order.PayMoney},{request.IcTradeNO}", OrderCode = order.OrderCode };
					return new BaseResult<PaymentRsp>(pp, 0, "");
			}
		}

		private async Task<string> PreOrderChangeStatus(string orderCode, string mobile, int type, int payMethod, string resBillNo)
		{
			var url = "Pred/v3/Order/ChangeStatus";
			var data = new { orderCode, mobile, type, payMethod, resBillNo };
			var result = await PostAsync(url, JsonConvert.SerializeObject(data)).ConfigureAwait(false);
			return result;
		}
	}
}
